package marking.liu.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import marking.liu.annotation.TimeTotal;
import marking.liu.constant.ParseTypeConstant;
import marking.liu.mapper.StockBlockRtInfoMapper;
import marking.liu.mapper.StockBusinessMapper;
import marking.liu.mapper.StockMarketIndexInfoMapper;
import marking.liu.mapper.StockRtInfoMapper;
import marking.liu.pojo.entity.StockBlockRtInfo;
import marking.liu.properties.StockInfoProperties;
import marking.liu.service.StockTimerTaskService;
import marking.liu.utils.IdWorkerUtil;
import marking.liu.utils.ParserStockInfoUtil;

import org.joda.time.DateTime;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private StockInfoProperties stockInfoProperties;
    @Autowired
    private IdWorkerUtil idWorkerUtil;
    @Autowired
    private ParserStockInfoUtil parserStockInfoUtil;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockBusinessMapper stockBusinessMapper;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;
    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 获取国内大盘的实时数据信息
     */
    public void getInnerMarketInfo() {
        String marketUrl = stockInfoProperties.getMarketUrl();
//        1、获取请求路jing
        String url = stockInfoProperties.getMarketUrl() + String.join(",", stockInfoProperties.getInner());
//        log.info("url为:{}", url);
//        2、封装请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add("referer", "https://finance.sina.com.cn/realstock/company/sh000300/nc.shtml");
        headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0");
//        3、组装请求对象
        HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
//        log.info("请求头为:{}", httpEntity.getHeaders());
//        4、发送请求
        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
        log.info("获取到的响应体为:{}", result.getBody());
        String responseBody = result.getBody();

        List stockMarketIndexInfoList = parserStockInfoUtil.parser4StockOrMarketInfo(responseBody, ParseTypeConstant.INNER);
//        向mapper插入数据
        stockMarketIndexInfoMapper.insertBatch(stockMarketIndexInfoList);

        //通知后台终端刷新本地缓存，发送的日期数据是告知对方当前更新的股票数据所在时间点
        rabbitTemplate.convertAndSend("innerMarketTopicExchange","inner.market",new Date());
    }

    /**
     * 量获取股票分时数据详情信息
     * http://hq.sinajs.cn/list=sz000002,sh600015
     */
    @TimeTotal
    public void getStockRtIndex() {
//        1、获取请求路径的股票编码
        List<String> allStockCode = stockBusinessMapper.getAllStockCode();
        allStockCode = allStockCode.stream().map(item1 -> item1.startsWith("0")? "sh"+item1 : "sz"+item1).collect(Collectors.toList());
        log.info("allStockCode集合为:{}", allStockCode);
        List<List<String>> partitioned = Lists.partition(allStockCode, 20);
        log.info("partitioned集合为:{}", partitioned);
        partitioned.forEach(item -> {
//            方案一： 同步获取

//            String url = stockInfoProperties.getMarketUrl() + String.join("," , item);
//            log.info("请求的url为:{}", url);
////            2、封装请求头
//            HttpHeaders headers = new HttpHeaders();
//            headers.add("referer", "https://finance.sina.com.cn/realstock/company/sh000300/nc.shtml");
//            headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0");
////            3、封装请求体
//            HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
////            4、发送get请求
//            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
////            5、获取请求体
//            String responseBody = response.getBody();
//            log.info("获取后的数据:{}", responseBody);
//
////            6、解析响应数据
//            List list = parserStockInfoUtil.parser4StockOrMarketInfo(responseBody, ParseTypeConstant.ASHARE);
//            log.info("获取后的数据进行解析:{}", list);
//
//            stockRtInfoMapper.insertBatch(list);

//            方案二 采用线程池进行获取

            threadPoolTaskExecutor.execute(() -> {
                log.info("开始使用线程池进行数据采集");
            String url = stockInfoProperties.getMarketUrl() + String.join("," , item);
            log.info("请求的url为:{}", url);
//            2、封装请求头
            HttpHeaders headers = new HttpHeaders();
            headers.add("referer", "https://finance.sina.com.cn/realstock/company/sh000300/nc.shtml");
            headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0");
//            3、封装请求体
            HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
//            4、发送get请求
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
//            5、获取请求体
            String responseBody = response.getBody();
            log.info("获取后的数据:{}", responseBody);

//            6、解析响应数据
            List list = parserStockInfoUtil.parser4StockOrMarketInfo(responseBody, ParseTypeConstant.ASHARE);
            log.info("获取后的数据进行解析:{}", list);
            stockRtInfoMapper.insertBatch(list);
            });
        });
    }

    /**
     * 板块实时数据采集
     * https://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php
     */
    public void getStockBlock() {
        String url = "https://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php";
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
//        获取响应数据
        String responseBody = response.getBody();
        log.info("响应数据为:{}", responseBody);
//        定义正则表达式
//        String reg = "\\{([^}]*)\\}";
        String reg = "\\=(.*)";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(responseBody);
        if (matcher.find()) {
//            log.info("截取:{}", matcher.group(1));
//            将获取的响应数据转换为map格式
            Map responseMap = JSONObject.parseObject(matcher.group(1)).toJavaObject(Map.class);
//            log.info("获取的map集合为:{}", responseMap);
            Set set = responseMap.keySet();
            set.stream().forEach(item -> {
//                获取value的所有信息
                String itemString = responseMap.get(item).toString();
                String[] split = itemString.split(",");
                StockBlockRtInfo stockBlockRtInfo = StockBlockRtInfo.builder()
                        .id(idWorkerUtil.nextId())
                        .label(split[0])
                        .blockName(split[1])
                        .companyNum(Integer.valueOf(split[2]))
                        .avgPrice(new BigDecimal(split[3]).setScale(3, RoundingMode.HALF_UP))
                        .updownRate(new BigDecimal(split[5]).setScale(3, RoundingMode.HALF_UP))
                        .tradeAmount(Long.valueOf(split[6]))
                        .tradeVolume(new BigDecimal(split[7]).setScale(3, RoundingMode.HALF_UP))
                        .curTime(DateTime.now().toDate())
                        .build();
//                log.info("当前股票板块对象信息:{}", stockBlockRtInfo);
                stockBlockRtInfoMapper.addBatch(stockBlockRtInfo);

            });
        }

    }
}
